#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <iostream>
#include <functional>
#include "log.hpp"
#include "threadPool.hpp"
#include "task.hpp"
#include "daemon.hpp"

extern Log lg;

extern const uint16_t DEFAULT_PORT;
extern const std::string DEFAULT_IP;
extern const int backlog;
extern const int BUFFER_SIZE;

enum ERR
{
    SOCK_ERR = 1,
    BIND_ERR,
    LISTEN_ERR
};

class tcpServer
{
public:
    tcpServer(uint16_t port = DEFAULT_PORT, std::string ip = DEFAULT_IP)
        :_listenfd(-1), _port(port), _ip(ip), _isrunning(false)
    { }

    void init()
    {
        //忽略SIGPIPE信号
        signal(SIGPIPE, SIG_IGN);
        //创建监听套接字
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_listenfd < 0) {
            lg(FATAL, "socket err, errno:%d, errmsg:%s", errno, strerror(errno));
            exit(SOCK_ERR);
        }
        lg(LOG, "socket success, errno:%d, errmsg:%s", errno, strerror(errno));
        //绑定ip和端口号
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;
        socklen_t len = sizeof(local);
        if(bind(_listenfd, (const sockaddr*)&local, len) < 0) {
            lg(FATAL, "bind err, errno:%d, errmsg:%s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(LOG, "bind success, errno:%d, errmsg:%s", errno, strerror(errno));
        //进入监听状态
        if(listen(_listenfd, backlog) < 0) {
            lg(FATAL, "listen err, errno:%d, errmsg:%s", errno, strerror(errno));
            exit(LISTEN_ERR);
        }
        lg(LOG, "listen success, errno:%d, errmsg:%s", errno, strerror(errno));
    }

    void run()
    {
        // Daemon();
        // daemon(1, 0);
        //启动线程池
        threadPool<int>::getInstance()->start();
        _isrunning = true;
        while(_isrunning)
        {
            struct sockaddr_in client;
            memset(&client, 0, sizeof(client));
            socklen_t len = 0;
            //接收连接
            int fd = accept(_listenfd, (sockaddr*)&client, &len);
            if(fd < 0) {
                lg(WARNING, "accept err, errno:%d, errmsg:%s", errno, strerror(errno));
                continue;
            }
            lg(LOG, "accept success, errno:%d, errmsg:%s", errno, strerror(errno));

            char clientipbuffer[32]; clientipbuffer[0] = 0;
            inet_ntop(AF_INET, &(client.sin_addr), clientipbuffer, sizeof(clientipbuffer));
            uint16_t clientport = ntohs(client.sin_port);
            
            /*v多进程: */
            // pid_t id = fork();
            // if(id < 0) {
            //     lg(WARNING, "fork err, errno:%d, errmsg:%s", errno, strerror(errno));
            // }
            // else if(id == 0)
            // {
            //     //子进程
            //     //取消父进程阻塞等待
            //     if(fork() > 0) { exit(0); }
            //     close(_listenfd);
            //     task(fd);
            //     exit(0);
            // }
            // //父进程
            // close(fd);
            // waitpid(id, nullptr, 0);

            /*v线程池: */
            //投放任务
            threadPool<int>::getInstance()->push(fd);
        }
        _isrunning = false;
    }

private:
    int _listenfd;
    uint16_t _port;
    std::string _ip;
    bool _isrunning;
};
